using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Storage;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;


namespace FEClone
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    /// 
    [Serializable]
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Map myMap;
        Unit myUnit;
        Unit myUnit2;
        const int mapWidth = 10;
        const int mapHeight = 10;
        const int tileSize = 16;
        String FEUserFolder;
        public enum GameModes { Initialising, SelectGameToLoad, GameLoaded };
        private GameModes curGameMode = GameModes.Initialising;
        private StorageDevice curGameStorageDevice;
        IAsyncResult gameLoaderResultChecker;
        private KeyboardState lastKeyboardState;
        private GamePadState lastGamePadState;
        private Boolean gameLoadInProgress = false;
        private System.Text.Encoding encodingType;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            // The Gamer Services functionality must be initialized before you call this method. The easiest way to do that is to add a GamerServicesComponent to the Game.Components collection in the constructor of your Game class.
            Components.Add(new GamerServicesComponent(this));
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            this.IsMouseVisible = true;
            // TODO: Add your initialization logic here
            GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;

            base.Initialize();
            //UserFolder = Environment.CurrentDirectory
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Texture2D mapTexture;
            Texture2D spriteTexture;
            Texture2D movementTexture;
            Texture2D gridTexture;

            mapTexture = Content.Load<Texture2D>(@"Textures\TileSets\TileSetTest");
            spriteTexture = Content.Load<Texture2D>(@"Textures\testsprite");
            movementTexture = Content.Load<Texture2D>(@"Textures\image-translucent-blue-60.gif");
            gridTexture = Content.Load<Texture2D>(@"Textures\grid");

            Vector2 unitPosition = new Vector2((float)(16 * 2.5 * 4), (float)(16 * 2.5 * 3));

            myMap = new Map(mapTexture, spriteBatch, tileSize, mapWidth, mapHeight, movementTexture, gridTexture);
            Boolean[,] movementRangeGrid = myMap.calculateMovementRange(new Point(0, 0), null, 5);
            myUnit = new Unit(tileSize, spriteBatch, Vector2.Zero, spriteTexture);
            myUnit2 = new Unit(tileSize, spriteBatch, unitPosition, spriteTexture);
            myMap.UnitList.Add(myUnit);
            myMap.UnitList.Add(myUnit2);

            myMap.WriteMovementGridToConsole(movementRangeGrid);
            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            Vector2 cursorPosition = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);

            myMap.Update(cursorPosition, Mouse.GetState().LeftButton, 2.5f);

            // Allows the game to exit
            GamePadState curGamePadState = GamePad.GetState(PlayerIndex.One);
            if (curGamePadState.Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here

            KeyboardState ks = Keyboard.GetState();

            //ignore this broken camera code
            if (ks.IsKeyDown(Keys.Left))
            {
                Camera.Location.X = MathHelper.Clamp(Camera.Location.X - 2, 0, (myMap.MapWidth - mapWidth) * myMap.tileSize);
            }

            if (ks.IsKeyDown(Keys.Right))
            {
                Camera.Location.X = MathHelper.Clamp(Camera.Location.X + 2, 0, (myMap.MapWidth - mapWidth) * myMap.tileSize);
            }

            if (ks.IsKeyDown(Keys.Up))
            {
                Camera.Location.Y = MathHelper.Clamp(Camera.Location.Y - 2, 0, (myMap.MapHeight - mapHeight) * myMap.tileSize);
            }

            if (ks.IsKeyDown(Keys.Down))
            {
                Camera.Location.Y = MathHelper.Clamp(Camera.Location.Y + 2, 0, (myMap.MapHeight - mapHeight) * myMap.tileSize);
            }

            lastKeyboardState = ks;
            lastGamePadState = curGamePadState;
            base.Update(gameTime);
        }


        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();


            /*//Defines which tile will be displayed in the top left corner of the window. Divide by tile size to determine which tile on the map this corresponds to.
            Vector2 firstSquare = new Vector2(Camera.Location.X / myMap.tileSize, Camera.Location.Y / myMap.tileSize);
            int firstX = (int)firstSquare.X;
            int firstY = (int)firstSquare.Y;


            Vector2 squareOffset = new Vector2(Camera.Location.X % myMap.tileSize, Camera.Location.Y % myMap.tileSize);
            int offsetX = (int)squareOffset.X;
            int offsetY = (int)squareOffset.Y;*/
            myMap.Draw(2.5f);

            spriteBatch.End();



            //spriteBatch.Draw(TileEngine.TileSetTexture, new Rectangle(0,0,16,16), TileEngine.GetSourceRectangle(3, myMap.MapWidth), Color.White);




            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}
